﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DataTransferObject;

namespace DataTransferObject.MapUnMapTime
{
    public class MappingService
    {
        #region Attributes

        #endregion

        #region Constructor
        #endregion

        #region Properties
        #endregion

        #region Essential Method

        #region Map freeTimeList onto new time axis
        /// <summary>
        /// Maps the free time block.
        /// don vi chuan la minutes
        /// </summary>
        /// <param name="freeTimeList">The free time list.</param>
        /// <param name="result">The result.</param>
        public static void mapFreeTimeBlock(FreeTimeList freeTimeList, ref MappedFreeTimeList result)
        {
            //result.Offset = freeTimeList.FreeTimeBlockList[0].StartDateTime;
            result.Offset = new DateTime(freeTimeList.FreeTimeBlockList[0].StartDateTime.Year,
                                         freeTimeList.FreeTimeBlockList[0].StartDateTime.Month,
                                         freeTimeList.FreeTimeBlockList[0].StartDateTime.Day,
                                         freeTimeList.FreeTimeBlockList[0].StartDateTime.Hour,
                                         freeTimeList.FreeTimeBlockList[0].StartDateTime.Minute,
                                         0);
            //tạo một mappedFreeTimeBlock và add vào mappedFreeTimeList sau mỗi vòng for
            for (int i = 0; i < freeTimeList.FreeTimeBlockList.Count; i++)
            {
                //gán giá trị cho start và end datetime của mỗi block
                MappedFreeTimeBlock tempBlock = new MappedFreeTimeBlock();
                tempBlock.Start = (int)freeTimeList.FreeTimeBlockList[i].StartDateTime.Subtract(result.Offset).TotalMinutes;
                tempBlock.End = (int)freeTimeList.FreeTimeBlockList[i].EndDateTime.Subtract(result.Offset).TotalMinutes;
                result.Add(tempBlock);

            }            
           
        }
        #endregion

        #region unmap freeTimeList from the time axis
        /// <summary>
        /// Unmaps the free time list.
        /// don vi map la phut
        /// </summary>
        /// <param name="mappedFreeTimeList">The mapped free time list.</param>
        /// <param name="result">The result.</param>
        public static void unmapFreeTimeList(MappedFreeTimeList mappedFreeTimeList, ref FreeTimeList result)
        {
            for (int i = 0; i < mappedFreeTimeList.ListFreeTimeBlock.Count; i++)
            {
                result.FreeTimeBlockList[i].StartDateTime = mappedFreeTimeList.Offset.AddMinutes(mappedFreeTimeList.ListFreeTimeBlock[i].Start);

                result.FreeTimeBlockList[i].EndDateTime = mappedFreeTimeList.Offset.AddMinutes(mappedFreeTimeList.ListFreeTimeBlock[i].End);
            }
        }
        #endregion

        /*
        #region get freeWorkingHourBlock of a whole week
        /// <summary>
        /// list các freeWorkingHourBlock của 1 tuần
        /// </summary>
        /// <param name="workingHourItem">The working hour item.</param>
        /// <returns></returns>
        public static MappedFreeTimeList freeWorkingHourList(WorkingHourItem workingHourItem)
        {
            //so phut cua 1 tuan
            int periodOfTime = 7 * 24 * 60;
            MappedFreeTimeList result = new MappedFreeTimeList();

            bool[] workingHourBreak = new bool[periodOfTime];
            bool[] workingHourFree = new bool[periodOfTime];
            // khoi dong gia tri
            for (int i = 0; i < periodOfTime; i++)
            {
                workingHourBreak[i] = false;
                workingHourFree[i] = false;
            }

            FromTimeToTime temp;
            int startTime, toTime;
            for (int i = 0; i < 7; i++)
            {
                temp = workingHourItem.WorkingHourFTTT[i];
                startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                if (toTime == startTime)
                {
                    toTime += 24 * 60;
                }
                //vd: ngày đầu tiên: 1h30 -> starttime = 90 2:00 -> toTime = 120
                for (int j = startTime; j < toTime; j++)
                {
                    workingHourFree[j] = true;
                }

                #region switch case for break
                switch (workingHourItem.NumberOfBreak)
                {
                    case 0:
                        break;
                    case 1:
                        temp = workingHourItem.FirstBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }
                        break;

                    case 2:
                        temp = workingHourItem.FirstBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.SecondBreakFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }
                        break;

                    case 3:
                        temp = workingHourItem.FirstBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.SecondBreakFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.ThirdBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }
                        break;

                    case 4:
                        temp = workingHourItem.FirstBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.SecondBreakFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.ThirdBreadkFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }

                        temp = workingHourItem.FourthBreakFTTT[i];
                        startTime = temp.StartTime.Hour * 60 + temp.StartTime.Minute + i * 24 * 60;
                        toTime = temp.ToTime.Hour * 60 + temp.ToTime.Minute + i * 24 * 60;
                        for (int j = startTime; j < toTime; j++)
                        {
                            workingHourBreak[j] = true;
                        }
                        break;

                    default:
                        break;
                }
                #endregion
            }

            double start = 0;
            double end = 0;

            workingHourFree[0] = workingHourFree[0] && !workingHourBreak[0];
            if (workingHourFree[0])
            {
                start = 0;
            }

            for (int i = 1; i < periodOfTime; i++)
            {
                workingHourFree[i] = workingHourFree[i] && !workingHourBreak[i];
                if (workingHourFree[i] && !workingHourFree[i - 1])
                {
                    // đổi sang đơn vị chung là phút rồi^^
                    start = i;
                }

                else if (workingHourFree[i - 1] && !workingHourFree[i])
                {
                    end = i - 1;
                    MappedFreeTimeBlock mftBlock = new MappedFreeTimeBlock();
                    mftBlock.StartDateTime = start;
                    mftBlock.EndDateTime = end;
                    result.addFreeTimeBlockToList(mftBlock);
                }
            }
            return result;
        }
        #endregion
        */

        /*
        #region shift the freeWorkingHourList to the axis based on the offset of MappedFreeTimeList
        /// <summary>
        /// Maps the working hour base on MappedFreeTimeList's offset.
        /// </summary>
        /// <param name="workingHourItem">The working hour item.</param>
        /// <param name="offset">The offset.</param>
        public static MappedFreeTimeList mapWorkingHour(WorkingHourItem workingHourItem, DateTime offset)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            int DOWeek = 0;
            double newOffset = 0;
            //
            // viet ham quyet dinh xem nen cong them bao nhieu tuan
           // bay gio tam thoi cong 5 tuan:D
             //
            result = addWeek(workingHourItem, 5);

            #region switch case
            switch (offset.ToString("ddd"))
            {
                case "Mon":
                    DOWeek = 0;
                    break;

                case "Tue":
                    DOWeek = 1;
                    break;

                case "Wed":
                    DOWeek = 2;
                    break;

                case "Thu":
                    DOWeek = 3;
                    break;

                case "Fri":
                    DOWeek = 4;
                    break;

                case "Sat":
                    DOWeek = 5;
                    break;

                case "Sun":
                    DOWeek = 6;
                    break;
            }
            #endregion

            newOffset = DOWeek * 24 * 60 + offset.Hour * 60 + offset.Minute;
            int i;
            //
            // bo di nhung block som hon so voi newOffset
            //
            for (i = 0; i < result.FreeTimeBlockList.Count; i++)
            {
                if (result.FreeTimeBlockList[i].EndDateTime >= newOffset)
                {
                    if (result.FreeTimeBlockList[i].StartDateTime < newOffset)
                    {
                        result.FreeTimeBlockList[i].StartDateTime = newOffset;
                    }
                    break;
                }
            }

            for (int j = 0; j < i; j++)
            {
                result.FreeTimeBlockList.RemoveAt(0);
            }
            //
            // hai vong for ben duoi:
            // dich tu block thu i tro di (vong for phia tren) va shift ve offset moi
            //
            for (int j = 0; j < i; j++)
            {
                result.removeFreeTimeBlock(j);
            }

            for (int j = 0; j < result.FreeTimeBlockList.Count; j++)
            {
                result.FreeTimeBlockList[j].StartDateTime = result.FreeTimeBlockList[j].StartDateTime - newOffset;
                result.FreeTimeBlockList[j].EndDateTime = result.FreeTimeBlockList[j].EndDateTime - newOffset;
            }
            return result;
        }
        #endregion
        */

        #region shift the mappedFreeTimeList to the axis based on the offset of workingHourList
        public static MappedFreeTimeList shiftFTLBaseOnWKHour(MappedFreeTimeList mappedFreeTimeList, ref Double newOffset)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            DateTime offset = mappedFreeTimeList.Offset;

            newOffset = 0;
            int DOWeek = 0;
            #region switch case
            switch (offset.ToString("ddd"))
            {
                case "Mon":
                    DOWeek = 0;
                    break;

                case "Tue":
                    DOWeek = 1;
                    break;

                case "Wed":
                    DOWeek = 2;
                    break;

                case "Thu":
                    DOWeek = 3;
                    break;

                case "Fri":
                    DOWeek = 4;
                    break;

                case "Sat":
                    DOWeek = 5;
                    break;

                case "Sun":
                    DOWeek = 6;
                    break;
            }
            #endregion

            newOffset = DOWeek * 24 * 60 + offset.Hour * 60 + offset.Minute;

            //shift
            for (int i = 0; i < mappedFreeTimeList.ListFreeTimeBlock.Count; i++)
            {
                MappedFreeTimeBlock tempBlock = new MappedFreeTimeBlock();
                tempBlock.Start = (int)(mappedFreeTimeList.ListFreeTimeBlock[i].Start + newOffset);
                tempBlock.End = (int)(mappedFreeTimeList.ListFreeTimeBlock[i].End + newOffset);
                result.Add(tempBlock);
            }

            result.Offset = mappedFreeTimeList.Offset;
            return result;
        }
        #endregion

        #region merge cac workingHourList trong 1 tuan
        public static MappedFreeTimeList mergeWorkingHourList_1week(List<MappedFreeTimeList> workingHourList)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            int countWorkingHour = workingHourList.Count;
            bool[,] temp = new bool[countWorkingHour, 24 * 7 * 60];

            //intiate array
            for (int i = 0; i < countWorkingHour; i++)
            {
                for (int j = 0; j < 24 * 7 * 60; j++)
                {
                    temp[i, j] = false;
                }
            }

            //convert list to array
            for (int i = 0; i < countWorkingHour; i++)
            {
                if (workingHourList[i] != null)
                {
                    int start = 0;
                    int end = 0;
                    for (int j = 0; j < workingHourList[i].ListFreeTimeBlock.Count; j++)
                    {
                        start = (int)(workingHourList[i].ListFreeTimeBlock[j].Start);
                        end = (int)(workingHourList[i].ListFreeTimeBlock[j].End);
                        for (int k = start; k < end; k++)
                        {
                            temp[i, k] = true;
                        }
                    }
                }
            }

            //create result
            bool flag = false;
            for (int j = 0; j < 24 * 7 * 60; )//
            {
                int i = 0;
                while (!temp[i, j])
                {
                    i++;
                    if (i >= countWorkingHour)
                    {
                        break;
                    }
                }
                if (i >= countWorkingHour)
                {
                    j++;
                    continue;
                }
                if (!flag)
                {
                    flag = true;
                    MappedFreeTimeBlock tempBlock = new MappedFreeTimeBlock();
                    tempBlock.Start = j;
                    //add workinghourList vo block
                    
                    for (int m = 0; m < countWorkingHour; m++)
                    {
                        if (temp[m, j])
                        {
                            tempBlock.WorkingHour.Add(m);
                        }
                    }
                    //result.Add(tempBlock);
                    result.ListFreeTimeBlock.Add(tempBlock);
                    //kiem tra do dai cua Block
                    for (j = j + 1; j < 24 * 7 * 60; j++)
                    {
                        //for (int l = i; l < countWorkingHour; l++)
                        for (int l = 0; l < countWorkingHour; l++)
                        {
                            if (temp[l, j] != temp[l, j - 1])
                            {
                                flag = false;
                                tempBlock.End = j;
                                break;
                            }
                            else
                            {
                                continue;
                            }

                        }
                        if (!flag)
                            break;
                    }
                    if (j == 24 * 7 * 60)
                        tempBlock.End = j;
                }

            }

            return result;
        }
        #endregion

        #region add week to working hour list
        public static MappedFreeTimeList enlargeWorkingHourListToFTListSize(MappedFreeTimeList workingHourList, Double endFTListBlock)
        {

            MappedFreeTimeList result = new MappedFreeTimeList();
            result = workingHourList;
            int countWorkingHourBlock = workingHourList.ListFreeTimeBlock.Count;
            bool connectable = false;
            if (workingHourList.ListFreeTimeBlock.Last().End == 24 * 7 * 60 && workingHourList.ListFreeTimeBlock.First().Start == 0)
            {
                if(workingHourList.ListFreeTimeBlock.Last().WorkingHour.Count == workingHourList.ListFreeTimeBlock.Last().WorkingHour.Count)
                {
                    int i;
                    for (i = 0; i < workingHourList.ListFreeTimeBlock.Last().WorkingHour.Count; i++)
                    {
                        if (workingHourList.ListFreeTimeBlock.Last().WorkingHour.Count == workingHourList.ListFreeTimeBlock.First().WorkingHour.Count)
                        {
                            if (workingHourList.ListFreeTimeBlock.Last().WorkingHour[i] != workingHourList.ListFreeTimeBlock.First().WorkingHour[i])
                            {
                                connectable = false;
                                break;
                            }
                        }
                    }
                    if (i == workingHourList.ListFreeTimeBlock.Last().WorkingHour.Count)
                    {
                        connectable = true;
                    }
                }
                
            }

            if (connectable)
            {
                for (int i = 0; workingHourList.ListFreeTimeBlock.Last().End <= endFTListBlock; i++)
                {
                    result.ListFreeTimeBlock.Last().End = (i+1) * 7 * 24 * 60 + result.ListFreeTimeBlock.First().End;
                    for (int j = 1; j < countWorkingHourBlock; j++)
                    {
                        MappedFreeTimeBlock temp = new MappedFreeTimeBlock();
                        temp.Start = workingHourList.ListFreeTimeBlock[j].Start + (i+1) * 7 * 24 * 60;
                        temp.End = workingHourList.ListFreeTimeBlock[j].End + (i + 1) * 7 * 24 * 60;

                        for (int k = 0; k < workingHourList.ListFreeTimeBlock[j].WorkingHour.Count; k++)
                        {
                            int tempWorkingHourID;
                            tempWorkingHourID = workingHourList.ListFreeTimeBlock[j].WorkingHour[k];
                            temp.WorkingHour.Add(tempWorkingHourID);
                        }

                        //result.Add(temp);
                        result.ListFreeTimeBlock.Add(temp);
                    }
                }
            }
            else
            {
                for (int i = 0; result.ListFreeTimeBlock.Last().End <= endFTListBlock; i++)
                {
                    for (int j = 0; j < countWorkingHourBlock; j++)
                    {
                        MappedFreeTimeBlock temp = new MappedFreeTimeBlock();
                        temp.Start = workingHourList.ListFreeTimeBlock[j].Start + (i+1) * 7 * 24 * 60;
                        temp.End = workingHourList.ListFreeTimeBlock[j].End + (i + 1) * 7 * 24 * 60;
                        temp.WorkingHour = new List<int>();
                        for (int k = 0; k < workingHourList.ListFreeTimeBlock[j].WorkingHour.Count; k++)
                        {
                            int tempWorkingHourID;
                            tempWorkingHourID = workingHourList.ListFreeTimeBlock[j].WorkingHour[k];
                            temp.WorkingHour.Add(tempWorkingHourID);
                        }

                        //result.Add(temp);
                        result.ListFreeTimeBlock.Add(temp);
                    }
                }
            }
            return result;
        }

        #endregion

        #region intersect Block va List
        public static MappedFreeTimeList intersectBlockAndList(MappedFreeTimeBlock Block, MappedFreeTimeList List)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();

            for (int i = 0; i < List.ListFreeTimeBlock.Count; i++)
            {
                if (List.ListFreeTimeBlock[i].End > Block.Start && List.ListFreeTimeBlock[i].Start < Block.End)
                {
                    MappedFreeTimeBlock tempBlock = new MappedFreeTimeBlock();

                    for (int k = 0; k < Block.WorkingHour.Count; k++)
                    {
                        int tempWorkingHourID;
                        tempWorkingHourID = Block.WorkingHour[k];
                        tempBlock.WorkingHour.Add(tempWorkingHourID);
                    }


                    tempBlock.Start = Block.Start > List.ListFreeTimeBlock[i].Start ? Block.Start :
                                                                                                                     List.ListFreeTimeBlock[i].Start;
                    if (List.ListFreeTimeBlock[i].End >= Block.End)
                    {
                        tempBlock.End = Block.End;
                        //result.Add(tempBlock);
                        result.ListFreeTimeBlock.Add(tempBlock);
                        break;
                    }
                    else
                    {
                        tempBlock.End = List.ListFreeTimeBlock[i].End;
                        //result.Add(tempBlock);
                        result.ListFreeTimeBlock.Add(tempBlock);
                        Block.Start = tempBlock.End;
                    }
                }

            }

            return result;
        }
        #endregion

        #region intersect List va List (co quan tam den thanh phan workingHour cua tung Task)
        public static MappedFreeTimeList intersectLists(MappedFreeTimeList workingHourList, MappedFreeTimeList globalList)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            MappedFreeTimeList temp;
            int count = workingHourList.ListFreeTimeBlock.Count;
            for (int i = 0; i < count; i++)
            {
                temp = intersectBlockAndList(workingHourList.ListFreeTimeBlock[i], globalList);
                for (int j = 0; j < temp.ListFreeTimeBlock.Count; j++)
                {
                    result.ListFreeTimeBlock.Add(temp.ListFreeTimeBlock[j]);
                }
            }
            result.Offset = globalList.Offset;

            return result;
        }

        #endregion

        #region return List1 - List2 (minus)
        /// <summary>
        /// Minuses the list.
        /// </summary>
        /// <param name="List1">The list1.</param>
        /// <param name="List2">The list2.</param>
        /// <returns></returns>
        public static MappedFreeTimeList minusList(MappedFreeTimeList List1, MappedFreeTimeList List2)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            int max;
            if (List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End >= List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End)
                max = (int)(List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End);
            else
                max = (int)(List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End);

            bool[] list1 = new bool[max];
            bool[] list2 = new bool[max];

            //initiate array
            for (int i = 0; i < max; i++)
            {
                list1[i] = false;
                list2[i] = true;
            }

            //convert List to array
            int start = 0;
            int end = 0;
            for (int i = 0; i < List1.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List1.ListFreeTimeBlock[i].Start);
                end = (int)(List1.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list1[j] = true;
                }
            }

            for (int i = 0; i < List2.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List2.ListFreeTimeBlock[i].Start);
                end = (int)(List2.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list2[j] = false;
                }
            }

            for (int i = 0; i < max; i++)
            {
                list1[i] = list1[i] && list2[i];
            }

            //convert array to List
            if (list1[0])
                start = 0;
            for (int i = 1; i < max; i++)
            {
                if (list1[i] && !list1[i - 1])
                    start = i;
                else if (list1[i - 1] && !list1[i])
                {
                    end = i - 1;
                    MappedFreeTimeBlock mftBlock = new MappedFreeTimeBlock();
                    mftBlock.Start = start;
                    mftBlock.End = end;
                    //result.Add(mftBlock);
                    result.ListFreeTimeBlock.Add(mftBlock);
                }
            }
            return result;
        }
        #endregion

        /*
        #region add a number of weeks to a freeWorkingHourList
        /// <summary>
        /// Adds the week.
        /// </summary>
        /// <param name="workingHourItem">The working hour item.</param>
        /// <param name="numberOfWeek">The number of week.</param>
        /// <returns></returns>
        public static MappedFreeTimeList addWeek(WorkingHourItem workingHourItem, int numberOfWeek)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();
            result = freeWorkingHourList(workingHourItem);
            int numberOfblockPerWeek = result.FreeTimeBlockList.Count;
            bool weekContinuous;
            weekContinuous = (result.FreeTimeBlockList[0].StartDateTime == 0
                && result.FreeTimeBlockList[numberOfblockPerWeek - 1].EndDateTime == 7 * 24 * 60 - 1);
            if (weekContinuous)
            {
                for (int i = 0; i < numberOfWeek; i++)
                {
                    result.FreeTimeBlockList[numberOfblockPerWeek].EndDateTime = i * 7 * 24 * 60 + result.FreeTimeBlockList[0].EndDateTime;
                    for (int j = 1; j < numberOfblockPerWeek; j++)
                    {
                        MappedFreeTimeBlock temp = new MappedFreeTimeBlock();
                        temp = result.FreeTimeBlockList[j];
                        result.addFreeTimeBlockToList(temp);
                    }
                }
            }
            else
            {
                int countBlockOfWeek = result.FreeTimeBlockList.Count;
                for (int i = 0; i < numberOfWeek; i++)
                {
                    for (int j = 0; j < countBlockOfWeek; j++)
                    {
                        MappedFreeTimeBlock temp = new MappedFreeTimeBlock();
                        temp.StartDateTime = result.FreeTimeBlockList[j].StartDateTime + (i+1) * 7 * 24 * 60;
                        temp.EndDateTime = result.FreeTimeBlockList[j].EndDateTime + (i+1) * 7 * 24 * 60;
                        result.addFreeTimeBlockToList(temp);
                    }
                }
            }
            return result;
        }
        #endregion
        */

        #region return List1 intersect List2
        /// <summary>
        /// Intersects the free time list.
        /// </summary>
        /// <param name="List1">The list1.</param>
        /// <param name="List2">The list2.</param>
        /// <returns></returns>
        public static MappedFreeTimeList intersectFreeTimeList(MappedFreeTimeList List1, MappedFreeTimeList List2)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();

            int max;
            if (List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End >= List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End)
                max = (int)(List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End);
            else max = (int)(List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End);

            bool[] list1 = new bool[max];
            bool[] list2 = new bool[max];

            //initiate array
            for (int i = 0; i < max; i++)
            {
                list1[i] = list2[i] = false;
            }

            //convert List to array
            int start = 0;
            int end = 0;
            for (int i = 0; i < List1.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List1.ListFreeTimeBlock[i].Start);
                end = (int)(List1.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list1[j] = true;
                }
            }

            for (int i = 0; i < List2.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List2.ListFreeTimeBlock[i].Start);
                end = (int)(List2.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list2[j] = true;
                }
            }

            for (int i = 0; i < max; i++)
            {
                list1[i] = list1[i] && list2[i];
            }

            //convert array to List
            if (list1[0])
                start = 0;
            for (int i = 1; i < max; i++)
            {
                if (list1[i] && !list1[i - 1])
                    start = i;
                else if (list1[i - 1] && !list1[i])
                {
                    end = i - 1;
                    MappedFreeTimeBlock mftBlock = new MappedFreeTimeBlock();
                    mftBlock.Start = start;
                    mftBlock.End = end;

                    result.Add(mftBlock);
                }
            }

            return result;
        }
        #endregion

        #region return List1 union List2
        /// <summary>
        /// Unions the free time list.
        /// </summary>
        /// <param name="List1">The list1.</param>
        /// <param name="List2">The list2.</param>
        /// <returns></returns>
        public static MappedFreeTimeList unionFreeTimeList(MappedFreeTimeList List1, MappedFreeTimeList List2)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();

            int max;
            if (List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End >= List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End)
                max = (int)(List1.ListFreeTimeBlock[List1.ListFreeTimeBlock.Count - 1].End);
            else max = (int)(List2.ListFreeTimeBlock[List2.ListFreeTimeBlock.Count - 1].End);

            bool[] list1 = new bool[max];
            bool[] list2 = new bool[max];

            //initiate array
            for (int i = 0; i < max; i++)
            {
                list1[i] = list2[i] = false;
            }

            //convert List to array
            int start = 0;
            int end = 0;
            for (int i = 0; i < List1.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List1.ListFreeTimeBlock[i].Start);
                end = (int)(List1.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list1[j] = true;
                }
            }

            for (int i = 0; i < List2.ListFreeTimeBlock.Count; i++)
            {
                start = (int)(List2.ListFreeTimeBlock[i].Start);
                end = (int)(List2.ListFreeTimeBlock[i].End);
                for (int j = start; j < end; j++)
                {
                    list2[j] = true;
                }
            }

            for (int i = 0; i < max; i++)
            {
                list1[i] = list1[i] || list2[i];
            }

            //convert array to List
            if (list1[0])
                start = 0;
            for (int i = 1; i < max; i++)
            {
                if (list1[i] && !list1[i - 1])
                    start = i;
                else if (list1[i - 1] && !list1[i])
                {
                    end = i - 1;
                    MappedFreeTimeBlock mftBlock = new MappedFreeTimeBlock();
                    mftBlock.Start = start;
                    mftBlock.End = end;

                    result.Add(mftBlock);
                }
            }

            return result;
        }
        #endregion

        #region return a List which is the result of union multiple MappedFreeTimeList
        public static MappedFreeTimeList unionMultipleFreeTimeList(List<MappedFreeTimeList> input)
        {
            MappedFreeTimeList result = new MappedFreeTimeList();

            long max;
            int count = input.Count;

            max = (long)input[0].ListFreeTimeBlock[input[0].ListFreeTimeBlock.Count - 1].End;
            for (int i = 0; i < count; i++)
            {
                if (max < (long)input[i].ListFreeTimeBlock[input[i].ListFreeTimeBlock.Count - 1].End)
                    max = (long)input[i].ListFreeTimeBlock[input[i].ListFreeTimeBlock.Count - 1].End;
                //max = (long)input[i].FreeTimeBlockList[input[i].FreeTimeBlockList.Count - 1].EndDateTime;
            }


            bool[] list1 = new bool[max];
            bool[] list2 = new bool[max];

            //initiate array
            for (int i = 0; i < max; i++)
            {
                list1[i] = list2[i] = false;
            }

            //convert List to array
            int start = 0;
            int end = 0;

            for (int k = 1; k < input.Count; k++)
            {
                for (int i = 0; i < input[k].ListFreeTimeBlock.Count; i++)
                {
                    start = (input[k].ListFreeTimeBlock[i].Start);
                    end = (input[k].ListFreeTimeBlock[i].End);
                    for (int j = start; j < end; j++)
                    {
                        list1[j] = true;
                    }
                }
            }

            //convert array to List
            if (list1[0])
                start = 0;
            for (int i = 1; i < max; i++)
            {
                if (list1[i] && !list1[i - 1])
                    start = i;
                else if (list1[i - 1] && !list1[i])
                {
                    end = i - 1;
                    MappedFreeTimeBlock mftBlock = new MappedFreeTimeBlock();
                    mftBlock.Start = start;
                    mftBlock.End = end;

                    result.Add(mftBlock);
                }
            }

            return result;
        }
        #endregion

        #region Noi list 2 vao sau list 1.
        /// <summary>
        /// Noi list2 vao sau list1. start cua list2 sau end cua list1
        /// ket qua cuoi cung duoc luu trong list1
        /// </summary>
        /// <param name="List1">The list1.</param>
        /// <param name="List2">The list2.</param>
        public static void connectFreeTimeList(ref MappedFreeTimeList List1, MappedFreeTimeList List2)
        {
            int count = List1.ListFreeTimeBlock.Count;
            for (int i = 0; i < List2.ListFreeTimeBlock.Count; i++)
            {
                MappedFreeTimeBlock temp = new MappedFreeTimeBlock();
                temp = List2.ListFreeTimeBlock[i];
                List1.Add(temp);
            }

            if (List1.ListFreeTimeBlock[count].Start - List1.ListFreeTimeBlock[count - 1].End == 0)
            {
                List1.ListFreeTimeBlock[count - 1].End = List1.ListFreeTimeBlock[count].End;
                List1.removeFreeTimeBlock(count);
            }
        }
        #endregion

        #endregion


    }



}
